<?php


namespace UU\Suite\DingTalk;


use GuzzleHttp\Client;
use Psr\SimpleCache\CacheInterface;
use UU\Suite\Kernel\Contracts\AccessTokenInterface;
use UU\Suite\Kernel\Contracts\HttpClientInterface;

class AccessToken implements AccessTokenInterface
{
    /**
     * @var HttpClientInterface|Client
     */
    protected $httpClient;
    /**
     * @var CacheInterface|null
     */
    protected $cache;

    protected string $appId;
    protected string $secret;
    protected ?string $key = null;

    public function __construct(
        string $appId,
        string $secret,
        ?CacheInterface $cache = null,
        ?HttpClientInterface $httpClient = null,
        ?string $key = null
    )
    {
        $this->httpClient = $httpClient ?? new Client();
        $this->appId = $appId;
        $this->secret = $secret;
        $this->cache = $cache;
        $this->key = $key;
    }


    public function getKey(): string
    {
        return $this->key ?? $this->key = \sprintf('official_account.access_token.%s', $this->appId);
    }

    public function setKey(string $key): self
    {
        $this->key = $key;

        return $this;
    }

    /**
     */
    public function getToken(): string
    {
        $key = $this->getKey();

        if ($token = $this->cache->get($key)) {
            return $token;
        }
        $response = $this->httpClient->request(
            'GET',
            '/gettoken',
            [
                'query' => [
                    'appkey' => $this->appId,
                    'appsecret' => $this->secret,
                ],
            ]
        );

        if (empty($response['access_token'])) {
            throw new \HttpException('Failed to get access_token.');
        }
        $this->cache->set($key, $response['access_token'], \intval($response['expires_in']) - 100);
        return $response['access_token'];
    }


    public function toQuery(): array
    {
        return ['access_token' => $this->getToken()];
    }
}